#include "dig_domain_rbtree.h"
#include "zip_record_store.h"
#include "zip_pkg_list.h"
#include "zip_lru_list.h"
#include "dig_wire_name.h"
#include <pthread.h>
#include "zip_test_set.h"


struct record_store
{
    test_set_t *test_set; 
    lru_list_t  *lru_list_;
    uint32_t total_mem_size;
    domain_rbtree_t *domain_rbtree_;
};

record_store_t *
record_store_create()
{
    record_store_t *record_store = malloc(sizeof(record_store_t));
    if (!record_store)
        return NULL;
    record_store->test_set = test_set_create();
    ASSERT(record_store->test_set, "NULL");
    record_store->lru_list_ = lru_list_create();
    ASSERT(record_store->lru_list_, "lru list create failed");

    record_store->total_mem_size = 0;

    return record_store;
}

void
record_store_delete(record_store_t *record_store)
{
    test_set_destroy(record_store->test_set);
    lru_list_delete(record_store->lru_list_);
    free(record_store);
}

uint32_t
record_store_get_total_mem_size(record_store_t *record_store)
{
    return record_store->total_mem_size;
}


void
record_store_free_part_momery(record_store_t *record_store, uint32_t required_mem_size)
{
    ASSERT(record_store->total_mem_size > required_mem_size, "no mem to free\n");
    uint32_t freed_mem_size = 0;
    while(freed_mem_size < required_mem_size)
    {
        pkg_list_t *tail_list = lru_list_remove_tail_list(record_store->lru_list_);
        if (tail_list == NULL)
            break;

        freed_mem_size += pkg_list_mem_size(tail_list);
        wire_name_t *wire_name = (wire_name_t *)pkg_list_get_owner(tail_list);
        test_set_delete(record_store->test_set, wire_name);
    }

    record_store->total_mem_size -= freed_mem_size;
}

void 
record_store_insert_pkg(record_store_t *record_store,
                        wire_name_t *wire_name,
                        pkg_data_t *pkg_data)
{
    ASSERT(record_store && wire_name && pkg_data ,"pointer can not be NULL");
    //char name_buf[512];
    //wire_name_to_string(wire_name, name_buf);
    //printf("<<<<insert name %s\n", name_buf);

    uint32_t before_insert_mem_size = 0;
    test_node_t *test_node = test_set_insert(record_store->test_set, wire_name);
    ASSERT(test_node, "NULL NODE");
    pkg_list_t *list = test_node_get_data(test_node); 
    if (list == NULL)
    {
        list = pkg_list_create(NULL);     
        pkg_list_set_owner(list, wire_name_clone(wire_name));
        test_node_set_data(test_node, list);

        lru_list_insert(record_store->lru_list_, list);
    }
    else
    {
        before_insert_mem_size = pkg_list_mem_size(list);
        lru_list_revise(record_store->lru_list_, list);
    }
        
    pkg_data_t *node = pkg_list_search(list, pkg_data_get_type(pkg_data)); 
    if (node)
    {
        pkg_list_delete(list, node);
    }
    pkg_list_insert(list, pkg_data);

    record_store->total_mem_size += (pkg_list_mem_size(list) - before_insert_mem_size);
    printf("<<<<<<<<<store total mem size is %u\n", record_store->total_mem_size);

}

pkg_data_t *
record_store_get_pkg(record_store_t *record_store,
                   wire_name_t *wire_name,
                   uint8_t query_type)
{
    pkg_list_t *list = test_set_search(record_store->test_set, wire_name); 
    if (!list)
        return NULL;

    return  pkg_list_search(list, query_type);
}



